package com.hsmpay.qian4.service.ds.impl;

import com.hsmpay.common.pojo.qian4.Qian4SendLog;
import com.hsmpay.common.pojo.user.User;
import com.hsmpay.common.util.NumberUtil;
import com.hsmpay.mobile.action.account.officialAccPay.OfficialAccPayBaseAction;
import com.hsmpay.mobile.action.account.scanCodePay.MD5;
import com.hsmpay.mobile.action.account.scanCodePay.ScanCodePayParam;
import com.hsmpay.mobile.action.account.scanCodePay.SignUtils;
import com.hsmpay.mobile.action.account.scanCodePay.XmlUtils;
import com.hsmpay.mobile.pojo.trans.TransPriorSettle;
import com.hsmpay.mobile.service.trans.TransPriorSettleService;
import com.hsmpay.mobile.service.user.UserService;
import com.hsmpay.qian4.pojo.PurchaseResult;
import com.hsmpay.qian4.pojo.RevocationResult;
import com.hsmpay.qian4.service.ds.WeixinPayService;
import com.hsmpay.tencent.WXPay;
import com.hsmpay.tencent.common.RandomStringGenerator;
import com.hsmpay.tencent.common.XMLParser;
import com.hsmpay.tencent.protocol.pay_protocol.PublicScanPayReqData;
import com.hsmpay.utils.DesUtil;
import com.hsmpay.utils.WriteFile;
import com.hsmpay.utils.system.ConConfig;

import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service("weixinPayService")
public class WeixinPayServiceImpl implements WeixinPayService{

    public static WriteFile wf = new WriteFile("ds_JQScan");
    private static Logger log = Logger.getLogger(JQScanCodePayServiceImpl.class);
    private static final String version = "1.0.0";
   
    private static final String MD5Key = "4683462567867C6120A251F8A1B0D6A1";
    private static final String signType = "MD5";
    private static final String appid = ConConfig.getAttribute("WEIXIN_APPID");//微信公众号
    private static final String key = ConConfig.getAttribute("WEIXIN_KEY");//微信公众号
    private static final String requestIp = "118.145.2.70";//请求方公网IP
    public static String urlStr = ConConfig.getAttribute("URL_OFFICIAL");
    public String submchid = ConConfig.getAttribute("WEIXIN_SUBMCHID");

    @Resource(name = "transPriorSettleService")
    private TransPriorSettleService<TransPriorSettle, Long> transPriorSettleService;
    
    @Resource(name = "userService")
    protected UserService<User, Long> userService;
    
    
    
    /**
     * 微信公众号支付
     * @param send
     * @return
     * @throws Exception
     */
    public PurchaseResult getQRCode(Qian4SendLog send, ScanCodePayParam scanCodePayParam, String signatureRelPath) throws Exception {
    	 //通知地址
        String notify_url = "http://"+urlStr+"/proOneMobile/scanPay/scanPayNL_WeixinNotify.action";
        //String reqUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        //公众账号ID	
        //String appid = appid;
        //商户号
       // String mch_id = "1384671002";
        //设备号
        String device_info = "WEB";
        //随机字符串
        //String nonce_str = NumberUtil.generateRandomString(32);
        //商品描述
        String body= scanCodePayParam.getBody();
        //商户系统内部的订单号,32个字符内
        String out_trade_no = scanCodePayParam.getOutTradeNo();
        //总金额
        double totalFee = Double.valueOf(scanCodePayParam.getTotalFee());
        int total_fee = NumberUtil.roundF2(totalFee*100).intValue();
        //终端IP
        String spbill_create_ip = requestIp;
        //交易类型
        String trade_type = "JSAPI";
        //用户标识
        String openid= scanCodePayParam.getSubOpenId();
        //签名
        //String sign = "";
      
        wf.log("【微信-收款 请求参数】outTradeNo: "+out_trade_no, "调试");
        wf.log("【微信-收款 请求参数】totalFee: "+total_fee, "调试");
        wf.log("【微信-收款 请求参数】appid: "+appid, "调试");
        wf.log("【微信-收款 请求参数】openid: "+openid, "调试");

        Map<String, Object> resultMap = new HashMap<String, Object>();
        if(ConConfig.isFormal()){
            wf.log("【微信-收款】请求环境:生产环境", "调试");
            try {
            	Long userId = send.getUserId();
            	User user = userService.getUserById(userId);
            	if(user.getRoleType() == 2){
            		submchid = user.getMerchantId();
            	}
            	PublicScanPayReqData scanPayReqData = new PublicScanPayReqData(openid,submchid,notify_url,trade_type, body, "", out_trade_no, total_fee, device_info, spbill_create_ip, "", "", "");
            	String info = WXPay.requestScanPayService(scanPayReqData);
            	log.info("微信返回的信息："+info);
            	resultMap = XMLParser.getMapFromXML(info);
            }catch (Exception e){
                e.printStackTrace();
                log.error("【微信-收款】 系统异常!");
            }
        }else{
        	resultMap = XMLParser.getMapFromXML("");
        }

        PurchaseResult pr = new PurchaseResult();
        pr.setReqMsg("获取微信交易订单失败,请稍后再试!");
        pr.setStatus(OfficialAccPayBaseAction.TC_WEIXIN);

        if(resultMap.isEmpty()){
        	pr.setReqCode("0001");
            pr.setReqMsg("获取微信交易订单失败,请稍后再试!");
            return pr;
        }

        String return_code = String.valueOf(resultMap.get("return_code"));
        String return_msg = String.valueOf(resultMap.get("return_msg"));
      
		if (return_code.equals("SUCCESS") && return_msg.equals("OK")) {// 通讯成功
			
			
			String result_code = String.valueOf(resultMap.get("result_code"));
			if(result_code.equals("SUCCESS")){
				String prepay_id = String.valueOf(resultMap.get("prepay_id"));
				String appid = String.valueOf(resultMap.get("appid"));
				String timeStamp = String.valueOf(System.currentTimeMillis());
				String nonceStr = RandomStringGenerator.getRandomStringByLength(32);
				String sign2 = getSign(appid, timeStamp, nonceStr, prepay_id, "MD5", key);
				pr.setAppId(appid);
				pr.setTimestamp(timeStamp);
				pr.setNonceStr(nonceStr);
				pr.setPrepayId("prepay_id="+prepay_id);
				pr.setPaySign(sign2);
				pr.setResultCode(result_code);
				pr.setReqMsg("获取微信交易订单成功!");
				pr.setReqCode("0000");
			}

		}else {
            pr.setReqCode("0001");
            pr.setReqMsg(return_msg);
        }
        return pr;
    }
    
    private  String getSign(String appId,String timeStamp,String nonceStr,String prepay_id,String signType,String key){
    	 Map<String, String> map =  new HashMap<String, String>();
    	 map.put("appId", appId);
    	 map.put("timeStamp", timeStamp);
    	 map.put("nonceStr", nonceStr);
    	 map.put("package", "prepay_id="+prepay_id);
    	 map.put("signType", signType);
    	 Map<String,String> params = SignUtils.paraFilter(map);
         StringBuilder buf = new StringBuilder((params.size() +1) * 10);
         SignUtils.buildPayParams(buf,params,false);
         String preStr = buf.toString();
         String sign = MD5.sign(preStr, "&key=" + key, "utf-8");
         return sign;
    }
    

    /**
     * 冲正
     * @param out_trade_no 商户系统内部订单号
     * @return
     * @throws Exception
     */
    public RevocationResult revocation(String out_trade_no)throws Exception {

        String reqUrl = "https://pay.swiftpass.cn/pay/gateway";
        String service = "unified.micropay.reverse";

        log.error("【微信-冲正 请求参数】out_trade_no: " + out_trade_no);
        wf.log("【微信-冲正 请求参数】out_trade_no: " + out_trade_no, "调试");

        String nonceStr = DesUtil.generate32Key();

        SortedMap<String,String> map = new TreeMap<>();
        map.put("service", service);
        map.put("version", version);
        map.put("sign_type", signType);
        map.put("mch_id", submchid);
        map.put("nonce_str", nonceStr);
        map.put("out_trade_no",out_trade_no);

        Map<String,String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() +1) * 10);
        SignUtils.buildPayParams(buf,params,false);
        String preStr = buf.toString();
        String sign = MD5.sign(preStr, "&key=" + MD5Key, "utf-8");

        map.put("sign",sign);

        log.error("【微信-冲正 请求参数】:" + XmlUtils.parseXML(map));

        Map<String, String> resultMap = new HashedMap();
        if(ConConfig.isFormal()){
            CloseableHttpResponse response = null;
            CloseableHttpClient client = null;
            try {
                HttpPost httpPost = new HttpPost(reqUrl);
                StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
                httpPost.setEntity(entityParams);
                httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
                client = HttpClients.createDefault();
                response = client.execute(httpPost);
                if (response != null && response.getEntity() != null) {
                    resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                }
            }catch (Exception e){
                e.printStackTrace();
                log.error("【微信-冲正】 系统异常!");
            }
        }else {
            //TODO:补充范例
            resultMap = null;
        }

        log.error("【微信-冲正 响应参数】:" + XmlUtils.toXml(resultMap));

        RevocationResult rr = new RevocationResult();
        rr.setReqCode("0001");
        rr.setReqMsg("交易撤消失败!");
        rr.setStatus(0);

        if(resultMap.isEmpty()){
            rr.setReqMsg("操作失败,系统未响应!");
            return rr;
        }

        //校验签名
        if(resultMap.containsKey("sign")){
            if(!SignUtils.checkParam(resultMap, MD5Key)) {
                rr.setReqMsg("验证签名不通过!");
                return rr;
            }
        }

        String status = resultMap.get("status");
        String message = resultMap.get("message");

        if(StringUtils.isNotBlank(message)){
            rr.setReqMsg(message);
            return rr;
        }

        if(status.equals("0")){
            String result_code  = resultMap.get("result_code");
            if(result_code.equals("0")){
                rr.setReqCode("0000");
                rr.setReqMsg("交易撤消成功!");
                rr.setStatus(1);
            }
        }else {
            String err_code = resultMap.get("err_code");
            rr.setReqMsg(err_code);
        }
        return rr;
    }


    /**
     * 查询交易订单
     * @param out_trade_no 商户系统内部订单号
     * @return RevocationResult
     * @throws Exception
     */
    public RevocationResult queryorder(String out_trade_no)throws Exception {

        String reqUrl = "url:https://pay.swiftpass.cn/pay/gateway";
        String service = "unified.trade.query";

        log.error("【微信-查询 请求参数】out_trade_no: " + out_trade_no);
        wf.log("【微信-查询 请求参数】out_trade_no: " + out_trade_no, "调试");

        String nonceStr = DesUtil.generate32Key();

        SortedMap<String,String> map = new TreeMap<>();
        map.put("service", service);
        map.put("version", version);
        map.put("sign_type", signType);
        map.put("mch_id", submchid);
        map.put("nonce_str", nonceStr);
        map.put("out_trade_no",out_trade_no);

        Map<String,String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() +1) * 10);
        SignUtils.buildPayParams(buf,params,false);
        String preStr = buf.toString();
        String sign = MD5.sign(preStr, "&key=" + MD5Key, "utf-8");

        map.put("sign",sign);
        log.error("【微信-查询 请求参数】:" + XmlUtils.parseXML(map));

        Map<String, String> resultMap = new HashedMap();

        if(ConConfig.isFormal()){
            CloseableHttpResponse response = null;
            CloseableHttpClient client = null;
            try {
                HttpPost httpPost = new HttpPost(reqUrl);
                StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
                httpPost.setEntity(entityParams);
                httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
                client = HttpClients.createDefault();
                response = client.execute(httpPost);
                if (response != null && response.getEntity() != null) {
                    resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                }
            }catch (Exception e){
                e.printStackTrace();
                log.error("微信-订单查询】 请求时系统异常!");
            }
        }else {
            resultMap = null;
        }

        log.error("【微信-查询 响应参数】:" + XmlUtils.toXml(resultMap));

        RevocationResult rr = new RevocationResult();
        rr.setReqCode("0001");
        rr.setReqMsg("查询交易订单失败!");
        rr.setStatus(0);

        if(resultMap.isEmpty()){
            rr.setReqMsg("操作失败,系统未响应!");
            return rr;
        }

        //校验签名
        if(resultMap.containsKey("sign")){
            if(!SignUtils.checkParam(resultMap, MD5Key)) {
                rr.setReqMsg("验证签名不通过!");
                return rr;
            }
        }

        String status = resultMap.get("status");
        String message = resultMap.get("message");

        if(status.equals("0")){
            String result_code = resultMap.get("result_code");
            if(result_code.equals("0")){
                String trade_state = resultMap.get("trade_states");
                if(trade_state.equals("SUCCESS")){
                    rr.setReqCode("0000");
                    rr.setReqMsg("交易成功!");
                    rr.setStatus(1);
                }else if(trade_state.equals("NOTPAY")){
                    rr.setReqCode("0002");
                    rr.setReqMsg("交易失败,请确认是否输入支付密码 !");
                    rr.setStatus(0);
                }else if(trade_state.equals("CLOSED")){
                    rr.setReqCode("0003");
                    rr.setReqMsg("交易已关闭 !");
                    rr.setStatus(0);
                }else if(trade_state.equals("REVOKED") || trade_state.equals("REFUND")){
                    rr.setReqCode("0004");
                    rr.setReqMsg("交易已撤销 !");
                    rr.setStatus(0);
                }else if(trade_state.equals("PAYERROR")){
                    rr.setReqCode("0001");
                    rr.setReqMsg("交易失败 !");
                    rr.setStatus(0);
                }else if(trade_state.equals("USERPAYING")){
                    rr.setReqCode("0005");
                    rr.setReqMsg("用户交易中!");
                    rr.setStatus(0);
                }
            }else {
                String err_msg = resultMap.get("err_msg");
                String err_code = resultMap.get("err_code");
                rr.setReqMsg(err_msg);
                rr.setReqCode(err_code);
            }
        }else {
            rr.setReqMsg(message);
        }
        return rr;
    }
}
